/*
 * Copyright (c) 2022 hpmicro
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "boot_user.h"
#include "uart_xmodem.h"
#include "flash_map.h"
#include "ota_api.h"
#include "string.h"
#include "ff.h"

FIL g_firmware;
extern FRESULT sd_fatfs_mount(void);
uint8_t firmware_readbuf[1024] = {0};
uint8_t temp_buf[SECTOR_SIZE] = {0};

/*
 * @brief :检测是否有SD卡插入，若插入，是否有对应固件？
 * @param :文件句柄
 * @return :0 ：没有SD卡插入
 * @return :1 ：有SD卡插入，且有对应固件
 * @return :2 ：有SD卡插入，但没有对应固件
 */
uint8_t fatfs_mount_and_seek_upgrade_firmware(FIL *file)
{
    FRESULT fatfs_result;
    if(sd_fatfs_mount()==FR_OK)
    { 
        fatfs_result = f_open (file,"upgrade_firmware.bin",FA_READ);
        if(fatfs_result == FR_OK)
        {
            return 1;
        }else{
            return 2;
        }
    }else{
        return 0;
    }
}
/*
 * @brief :将数据写入Flash
 * @param :data 数据源
 * @param :len 数据长度
 * @return :0
 */
static int writefile(unsigned char* data, int len)
{
    /* First packet contain file header info */
    ota_board_auto_write((void*)data, len);
    return 0;
}
/*
 * @brief :检测是否进入固件接收模式
 * @param :无
 * @return :-1 不进入固件接收模式 ， 1 进入固件接收模式
 */
int check_reception_mode(void)
{
    for(uint32_t i = 0;i<20;i++)
    {
        printf("\r\n");
    }
    printf("****************************************************\r\n");//清屏
    printf("**          welcome use bootloader                 *\r\n");
    printf("** 1 :Enter 1 to enter firmware reception mode     *\r\n");
    printf("** 2 :Enter any value (except 1) to enter the app  *\r\n");
    printf("****************************************************\r\n");
    int temp = getchar();

    if(temp != 49)//1的acsii吗
    {
        return -1;
    }else{
        return 1;
    }
}

/*
 * @brief :使用TF卡获取固件
 * @param :无
 * @return :void
 */
void tf_fatfs_receive(void)
{
    uint32_t read_back_num = 0;
    do
    {
        f_read(&g_firmware,firmware_readbuf,1024,&read_back_num);
        if(read_back_num!=0)
        {
            ota_board_auto_write((void*)firmware_readbuf, read_back_num);
        }
    }while(read_back_num!=0);

}

/*
 * @brief :使用xmodem协议获取固件
 * @param :无
 * @return :void
 */
void xmodem_receive(void)
{
    int ret = 0;
    ret = xmodemReceive(NULL, 0, writefile);
    board_delay_ms(100);
    printf("ret = %d\r\n",ret);
}

/*
 * @brief :选择用何种方法接收固件
 * @param :无
 * @return :void
 */
void firmware_receive(void)
{
    uint8_t fatfs_res;
    fatfs_res = fatfs_mount_and_seek_upgrade_firmware(&g_firmware);
    switch(fatfs_res)
    {
        case 0:printf("no SD CARD Insert using uart xmodem\r\n");xmodem_receive();break;//
        case 1:printf("SD CARD Inserted copy firmware now.......\r\n");tf_fatfs_receive();break;
        case 2:printf("SD CARD Insert but can not find firmware using uart xmodem\r\n");xmodem_receive();break;
    }
    printf("\r\nFirmware received done, please restart the MCU\r\n");

}

/*
 * @brief :将第二区间的固件拷贝到第一区间
 * @param :无
 * @return :void
 */
void firmware_copy(void)
{
    uint32_t index = 0;
    user_fota_header_t* fota_header = NULL;
    fota_header = (user_fota_header_t*)FLASH_APP2_HEADER_ADDR;
    printf("len = %d",fota_header->len);
    for(uint32_t i = 0;i<fota_header->len/SECTOR_SIZE;i++)
    {
        memcpy(temp_buf,FLASH_USER_APP2_ADDR+i*SECTOR_SIZE,SECTOR_SIZE);
        ota_board_flash_write(FLASH_USER_APP1_ADDR+i*SECTOR_SIZE,temp_buf,SECTOR_SIZE);
        index++;
    }
    memcpy(temp_buf,FLASH_USER_APP2_ADDR+index*SECTOR_SIZE,SECTOR_SIZE);
    ota_board_flash_write(FLASH_USER_APP1_ADDR+index*SECTOR_SIZE,temp_buf,fota_header->len%SECTOR_SIZE);
}

int main(void)
{
    int ret = 0;
    int bootmode = 0;
    bootuser_board_init();
    ota_board_flash_init();
    if(check_reception_mode() == 1)
    {
        printf("Start bootuser mode ota uart ota\r\n");
        firmware_receive();
    }else{
        bootmode = bootuser_verfiy_goto_app(true);
        switch(bootmode)
        {
            case -1:ota_board_app_jump(0);break;
            case 0:ota_board_flash_erase(1);ota_board_app_jump(0);break;
            case 1:firmware_copy();
            printf("Erasing buffer files........");ota_board_flash_erase(1);
            ota_board_app_jump(0);
            break;
            case 2:printf("Start bootuser mode ota uart ota\r\n");firmware_receive();break;
            default:printf("will never be here\r\n");break;
        }
    }

    while (1)
    {

    }
    return 0;
}


